"""
Copyright 2013, Thomas Dejanovic.
 
This is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.

This software is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this software; if not, write to the Free
Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA, or see the FSF site: http://www.fsf.org.
"""

# $Id:  $
# $URL: $
# $Author: $

from os import extsep
import to_hatch_structure
import hatch_iterators  # TODO Include this in a new parent "hatch_target.py" module. 
from hatch_constants import BASE_BIT, BIT_WIDTH, DATA_BUS_WIDTH, BASE_ADDRESS
from hatch_constants import SOFTWARE_ACCESS, READ_ACCESS, WRITE_ACCESS
from hatch_constants import GLOBAL_NAME, COMMENT, DEFAULT_VALUE
from hatch_register import Register
from hatch_struct import Pack, Struct

def generate(hatchNode, moduleName):
    """ Turns hatch code into a CSV (comma seperated value) file.
        'hatchNode' is the top node of the design.
        'moduleName' is the basename of the design file.
    """
    prevNameHash = {}

    outputFile = open(moduleName + extsep + "h", 'w')
    depthFirstIterator = hatch_iterators.HatchNodeIteratorDepthFirst(hatchNode)
    for node in depthFirstIterator:    # Depth first.
        n = node
        name = n.name
        while (prevNameHash.has_key(name)):
            # Houston, we have a problem
            n = n.parent
            name = n.name + "_" + name
        prevNameHash[name] = 1

        outputFile.write("\n#define %s_addr %d\n"%(name, node.properties.get(BASE_ADDRESS, "")))
        outputFile.write("\n#define %s_default %s\n"%(name, node.properties.get(DEFAULT_VALUE, "")))
        softAccess = node.properties.get(SOFTWARE_ACCESS, "")
        if (node.__class__.__name__ == Pack.__name__ or \
                (node.__class__.__name__ == Register.__name__ and \
                     node.parent.__class__.__name__ == Struct.__name__)):
            # this is a register read where we get all the data in a single read.
            if READ_ACCESS in softAccess:
                outputFile.write("#define %s_read()   dcom_read_register(%s_addr)\n"%\
                                     (name, name))
            else:
                outputFile.write("//      %s is not readable by software\n"%(name))
            if WRITE_ACCESS in softAccess:
                outputFile.write("#define %s_write(v) dcom_write_register(%s_addr,v)\n"%\
                                     (name, name));
            else:
                outputFile.write("//      %s is not writable by software\n"%(name))
        elif (node.__class__.__name__ == Register.__name__ and \
                  node.parent.__class__.__name__ == Pack.__name__):
            # this is a bit field in a larger register.
            baseBit = node.properties.get(BASE_BIT, 0)
            bitWidth = node.properties.get(BIT_WIDTH, 0)
            if READ_ACCESS in softAccess:
                outputFile.write("#define %s_read()   dcom_read_bit_field(%s_addr,%d,%d)\n"%\
                                     (name, name, baseBit, bitWidth));
            else:
                outputFile.write("//      %s is not readable by software\n"%(name))
            if WRITE_ACCESS in softAccess:
                outputFile.write("#define %s_write(v) dcom_write_bit_field(%s_addr,v,%d,%d)\n"%\
                                     (name, name, baseBit, bitWidth));
            else:
                outputFile.write("//      %s is not writable by software\n"%(name))
    outputFile.close()
